define(
  [
    'dojo/_base/declare',
    'dojo/on',
    'dojo/dom',
    'dojo/_base/lang',
    'dojo/dom-construct'
  ],
  function(declare, on, dom, lang, domConstruct)
  {
    return declare([],
      {
        classCode: 'FunctionManager',
        
        scale:null,
        startX:0,
        startY:0,
        endX:0,
        endY:0,
        _type:'',
        
        constructor:function(args)
        {
          console.log(this.classCode, "I'm in constructor", this.classCode);
        },
        
        postscript:function(args)
        {
          console.log(this.classCode, "I'm in postscript", this.classCode);
          
          this._type = args.type || 'exp';
          this.startX = args.startX || 0;
          this.startY = args.startY || 0;
          this.endX = args.endX || 100;
          this.endY = args.endY || 100;
          
          this._initScale();
        },
        
        fun:function()
        {
          var funName = this._type+"Fun";
          var funX = lang.hitch(this,this[funName+"X"]);
          var funY = lang.hitch(this,this[funName+"Y"]);
          var funRes =
          {
            X: lang.hitch(this,function(d, i, a)
              {
                return funX;
              }),
            Y: lang.hitch(this,function(d, i, a)
              {
                return funY;
              })
          };
          return funRes;
        },
        
        expFunX:function(/*Time [0,1]*/t)
        {
          if(isNaN(t))
          {
            return this.startX;
          }
          var x = (this.endX - this.startX)*t;
          x += this.startX;
          return x;
        },
        
        expFunY:function(/*Time [0,1]*/t)
        {
          if(isNaN(t))
          {
            return this.startY;
          }
          var x = (this.endX - this.startX)*t;
          x += this.startX;
          var y = this.expEval(x);
          y = this.scale(y);
          return y;
        },
        
        mineFunX:function(/*Time [0,1]*/t)
        {
          if(isNaN(t)){return 0;}
          var x = this.endX - this.startX;
          
          var dx = x/2;
          dx += this.startX;
          
          x = x*t;
          x += this.startX;
          
          return t<0.5 ? x : dx;
        },
        
        mineFunY:function(/*Time [0,1]*/t)
        {
          if(isNaN(t)){return 0;}
          var y = this.endY - this.startY;
          
          //var dy = y/2;
          //dy += this.startY;
          
          y = y*t;
          y += this.startY;
          
          return y;
        },
        
        expEval:function(x)
        {
          return x^2;
        },
        
        _initScale:function()
        {
          var evalFunName = this._type+"Eval";
          var evalFun = this[evalFunName];
          if(evalFun)
          {
            var domain = [evalFun(this.startX), evalFun(this.endX)];
            var range =[this.startY, this.endY];
            this.scale = d3.scale.linear()
            .domain(domain)
            .range(range);
          }
        },
        
        endOfLib:null
      });
  });